local Snake = class("Snake")

local Body = require "app.models.Body"

local cInitLen = 3

function Snake:ctor(node)
    self.BodyArray = {}
    self.node = node    

    for i = 1, cInitLen do 
    	self:Grow(1 == i)
    end

    self:SetDir("left")
end

function Snake:GetTailGrid()
	if #self.BodyArray == 0 then
		return 0, 0
	end
	-- #表示取数组的长度
	local tail = self.BodyArray[#self.BodyArray]
	return tail.x, tail.y
end

function Snake:GetHeadGrid()
	if #self.BodyArray == 0 then
		return nil
	end

	--注意LUA里数组下标从1开始而不是从0开始
	local head = self.BodyArray[1]
	return head.x, head.y
end

function Snake:SetHeadGrid(x, y)
	local head = self.BodyArray[1]
	head.x, head.y = x, y
end

function Snake:Grow( isHead )
	local tailX, tailY = self:GetTailGrid()
	local body = Body.new(self, tailX, tailY, self.node, isHead)
	--这个是一个数组，装的是Body对象
	table.insert(self.BodyArray, body)
end

local function OffsetGridByDir( x, y, dir )
	if dir == "left" then
		return x - 1, y
	elseif dir == "right" then
		return x + 1, y
	elseif dir == "up" then
		return x, y - 1
	elseif dir == "down" then
		return x, y + 1
	end

	print("unkonwn dir:", dir)
	return x, y
end

local hvTable = {
	["left"] = "h",
	["right"] = "h",
	["up"] = "v",
	["down"] = "v",
}

local rotTable = {
	["left"] = 0,
	["right"] = 180,
	["up"] = -90,
	["down"] = 90,
}

function Snake:SetDir( dir )
	--同轴互斥
	if hvTable[dir] == hvTable[self.MoveDir] then
		return
	end

	self.MoveDir = dir

	local head = self.BodyArray[1]
	--旋转蛇头
	head.sp:setRotation(rotTable[self.MoveDir])
end

function Snake:Update()
	if #self.BodyArray == 0 then
		return
	end

	for i = #self.BodyArray, 1, -1 do
		local body = self.BodyArray[i]
		if 1 == i then
			body.x, body.y = OffsetGridByDir(body.x, body.y, self.MoveDir)
		else
			local front = self.BodyArray[i - 1]
			body.x, body.y = front.x, front.y
		end

		SetCollide(body.x, body.y, { Name = string.format("body%d", i), Type = "body" })
		body:Update()
	end
end

function Snake:Blink(callback)
	for index, body in ipairs(self.BodyArray) do
		local blink = cc.Blink:create(3, 5)
		if 1 == index then
			local a = cc.Sequence:create(blink, cc.CallFunc:create(callback))
			body.sp:runAction(a)
		else
			body.sp:runAction(blink)
		end
	end
end

function Snake:Kill( )
	--亚元变量
	for _, body in ipairs(self.BodyArray) do 
		self.node:removeChild(body.sp)
	end
end

return Snake